package com.sr.aspect;

import com.sr.annotation.Log;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;

/**
 * @author xiaochi
 * @date 2022/4/30 15:26
 * @desc AspectAdvice
 */
@Slf4j
@Aspect
@Component
@RequiredArgsConstructor(onConstructor = @__)
@EnableAspectJAutoProxy(proxyTargetClass = true) // 使用cglib代理
public class AspectAdvice {

    private final LogAspect logAspect;
    private final Executor taskExecutor;

    /**
     * 环绕通知拦截
     * @param joinPoint
     * @return
     */
    @Around("execution(* com.sr.controller..*..*(..))")
    public Object handleAspect(ProceedingJoinPoint joinPoint) throws Throwable {
        long startTime = System.currentTimeMillis();
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
        Object[] args = joinPoint.getArgs();
        Object result = joinPoint.proceed(args);
        long time = System.currentTimeMillis() - startTime;
        log.info("接口地址{},请求方式{},参数{},时长{}毫秒",request.getRequestURI(),request.getMethod(),args,time);
        if (method.isAnnotationPresent(Log.class)){
            request.setAttribute("time",time);
            try {
                CompletableFuture.runAsync(() -> logAspect.execute(joinPoint,method,request),taskExecutor);
            }catch (Exception e){
                log.error("【记录操作日志异常】，{}",e);
            }
        }
        return result;
    }
}
